﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Serialization;

namespace Cms.Domain
{
    public class Administrator
    {
        private IList<Site> _availableSites;
        private DateTime _created;
        private Site _currentSite;
        private string _firstname;
        private bool _forceLogout;
        private PermissionChecker _hasPermission;
        private string _lastname;
        private int _selectedFolderID;
        private int _selectedMediaFolderID;
        private string _serializedSearchContentSettings;
        private string _username;
        private IList<VisitedAdminUrl> _visitedAdminUrls;
        private IList<VisitedPublicUrl> _visitedPublicUrls;
        private IList<int> _closedFolders;
        private IList<int> _closedMediaFolders;

        public Administrator()
        {
            _visitedAdminUrls = new List<VisitedAdminUrl>();
            _visitedPublicUrls = new List<VisitedPublicUrl>();
            _availableSites = new List<Site>();
            _selectedFolderID = -1;
            _selectedMediaFolderID = -1;
            _created = DateTime.Now;
            _forceLogout = false;
            _closedFolders = new List<int>();
            _closedMediaFolders = new List<int>();
        }

        public virtual int ID { get; set; }

        public virtual AdministratorGroup Group { get; set; }

        public virtual string Username
        {
            get { return _username; }
            set { _username = value; }
        }
        
        public virtual string Password { get; set; }

        public virtual string Email { get; set; }
        
        public virtual string Firstname
        {
            get { return _firstname; }
            set { _firstname = value; }
        }
        
        public virtual string Lastname
        {
            get { return _lastname; }
            set { _lastname = value; }
        }

        public virtual IList<int> ClosedFolders
        {
            get { return _closedFolders; }
            set { _closedFolders = value; }
        }

        public virtual IList<int> ClosedMediaFolders
        {
            get { return _closedMediaFolders; }
            set { _closedMediaFolders = value; }
        }

        public virtual bool Deleted { get; set; }
        
        public virtual Site DefaultSite { get; set; }

        public virtual string DefaultSystemLocale { get; set; }

        public virtual DateTime Created
        {
            get { return _created; }
            set { _created = value; }
        }

        public virtual DateTime? FirstLogin { get; set; }
        
        public virtual DateTime? LatestLogin { get; set; }

        public virtual Site CurrentSite
        {
            get { return _currentSite; }
            set { _currentSite = value; }
        }

        public virtual Locale CurrentSiteLocale { get; set; }
        
        public virtual IList<VisitedAdminUrl> VisitedAdminUrls
        {
            get { return _visitedAdminUrls; }
            set { _visitedAdminUrls = value; }
        }
        
        public virtual IList<VisitedPublicUrl> VisitedPublicUrls
        {
            get { return _visitedPublicUrls; }
            set { _visitedPublicUrls = value; }
        }
        
        public virtual string DateFormat { get; set; }

        public virtual string TimeFormat { get; set; }

        public virtual DayOfWeek? FirstDayOfWeek { get; set; }

        public virtual int SelectedFolderID
        {
            get { return _selectedFolderID; }
            set { _selectedFolderID = value; }
        }

        public virtual int SelectedMediaFolderID
        {
            get { return _selectedMediaFolderID; }
            set { _selectedMediaFolderID = value; }
        }
        
        public virtual string SerializedSearchContentSettings
        {
            get { return _serializedSearchContentSettings; }
            set { _serializedSearchContentSettings = value; }
        }

        public virtual bool ShowIntroHelp { get; set; }

        public virtual IList<Site> AvailableSites
        {
            get { return _availableSites; }
            set { _availableSites = value; }
        }
        
        public virtual PermissionChecker HasPermission
        {
            get
            {
                if (_hasPermission == null)
                {
                    _hasPermission = new PermissionChecker(this);
                }
                return _hasPermission;
            }
        }

        public virtual bool ForceLogout
        {
            get { return _forceLogout; }
            set { _forceLogout = value; }
        }
        
        public virtual string Fullname
        {
            get
            {
                if (!string.IsNullOrEmpty(_firstname) || !string.IsNullOrEmpty(_lastname))
                    return _firstname + " " + _lastname;
                return _username;
            }
        }
        
        public virtual void LogVisitedAdminUrl(string url, string header, string imageUrl)
        {
            // Delete earlier entries with the same url
            IEnumerable<VisitedAdminUrl> earlierVisitsEnumeration = from VisitedAdminUrl v in _visitedAdminUrls
                                                                    where v.Url.ToLower() == url.ToLower()
                                                                    select v;
            IList<VisitedAdminUrl> earlierVisits = new List<VisitedAdminUrl>(earlierVisitsEnumeration);
            foreach (VisitedAdminUrl v in earlierVisits)
            {
                v.Administrator = null;
                _visitedAdminUrls.Remove(v);
            }
            var visit = new VisitedAdminUrl
                            {
                                Administrator = this,
                                CurrentSite = _currentSite,
                                Header = header,
                                ImageUrl = imageUrl,
                                Timestamp = DateTime.Now,
                                Url = url
                            };
            _visitedAdminUrls.Add(visit);
        }

        public virtual void LogVisitedPublicUrl(Page page, string queryString)
        {
            // Delete earlier entries with the same url
            IEnumerable<VisitedPublicUrl> earlierVisitsEnumeration = from VisitedPublicUrl v in _visitedPublicUrls
                                                                     where v.Page.ID == page.ID
                                                                           &&
                                                                           v.QueryString.ToLower() ==
                                                                           queryString.ToLower()
                                                                     select v;
            IList<VisitedPublicUrl> earlierVisits = new List<VisitedPublicUrl>(earlierVisitsEnumeration);
            foreach (VisitedPublicUrl v in earlierVisits)
            {
                v.Administrator = null;
                v.Page = null;
                _visitedPublicUrls.Remove(v);
            }
            var visit = new VisitedPublicUrl
                            {
                                Page = page,
                                QueryString = queryString,
                                Administrator = this,
                                Timestamp = DateTime.Now
                            };
            _visitedPublicUrls.Add(visit);
        }

        public virtual SearchContentSettings GetSearchContentSettings()
        {
            if (_serializedSearchContentSettings == null)
                return null;
            try
            {
                byte[] compressedData = Convert.FromBase64String(_serializedSearchContentSettings);
                var ms = new MemoryStream(compressedData);
                var s = new XmlSerializer(typeof(SearchContentSettings));
                return (SearchContentSettings)s.Deserialize(ms);
            }
            catch (Exception)
            {
                _serializedSearchContentSettings = null;
                return null;
            }
        }
        
        public virtual void SetSearchContentSettings(SearchContentSettings settings)
        {
            try
            {
                var s = new XmlSerializer(typeof(SearchContentSettings));
                var settingsStream = new MemoryStream();
                s.Serialize(settingsStream, settings);
                _serializedSearchContentSettings = Convert.ToBase64String(settingsStream.ToArray());
            }
            catch (Exception)
            {
                _serializedSearchContentSettings = null;
            }
        }
    }
}